package cn.tedu.deviceservice.service.impl;

import cn.tedu.charging.common.pojo.vo.StationInfoVO;
import cn.tedu.deviceservice.service.DeviceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;

    /**
     * 查询附件充电桩
     * @param longitude
     * @param latitude
     * @param radius
     * @return
     */
    @Override
    public List<StationInfoVO> getNear(Double longitude, Double latitude, Double radius) {
        //todo redisGeo的使用
        //调用处理geo类型数据的方法
        BoundGeoOperations<String, Serializable> stationGEOs = redisTemplate.boundGeoOps("stations");
        //调用处理hash数据的方法
        HashOperations<String, Object, Object> opsForHash = redisTemplate.opsForHash();

        //根据传入参数的坐标,半径,划定圆形范围
        Point point=new Point(longitude,latitude);
        Distance distance = new Distance(radius, Metrics.KILOMETERS);
        Circle circle=new Circle(point,distance);

        //设置geo方法返回参数
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        //设置返回距离
        args.includeDistance();
        //设置返回坐标 经纬度
        args.includeCoordinates();

        //搜索圆形范围内符合的点
        GeoResults<RedisGeoCommands.GeoLocation<Serializable>> results = stationGEOs.radius(circle,args);
        log.debug("圆形半径内的点:{}",results);

        List<StationInfoVO> resultVos = new ArrayList<>();
        for (GeoResult<RedisGeoCommands.GeoLocation<Serializable>> result : results) {
            //获取站点和传入点的距离
            double stationDistance = result.getDistance().getValue();
            //获取站点经纬度 Point
            Point stationPoint = result.getContent().getPoint();
            //获取键名
            Serializable name = result.getContent().getName();
            //查询站点详情信息
            String stationId = String.valueOf(name);
            String fieldKey = "name";
            Object value = opsForHash.get(stationId, fieldKey);
            log.debug("通过stationId:{} 和 field-key:{} 获取值:{}",name,fieldKey,value);
            //获取hash里的所有键值对
            Map<Object, Object> entries = opsForHash.entries(stationId);
            log.debug("通过stationId:{}获取所有键值对:{}",name,entries);
            Object deviceNumberObj = entries.get("deviceNumber");
            Object codeObj = entries.get("stationCode");
            Object nameObj = entries.get("name");
            Object operatorId = entries.get("operatorId");

            //封装返回结果对象并且设置值
            StationInfoVO stationInfoVO = new StationInfoVO();
            stationInfoVO.setDistance(stationDistance);
            stationInfoVO.setStationId(Long.parseLong(stationId));
            stationInfoVO.setStationCode(String.valueOf(codeObj));
            stationInfoVO.setStationName(String.valueOf(nameObj));
            stationInfoVO.setDeviceNumber(Long.valueOf(String.valueOf(deviceNumberObj)));
            stationInfoVO.setOperatorId(Long.valueOf(String.valueOf(operatorId)));
            stationInfoVO.setLongitude(stationPoint.getX());
            stationInfoVO.setLatitude(stationPoint.getY());
            resultVos.add(stationInfoVO);
        }
        return resultVos;
    }
}
